package com.yueke.yuekeshop.shopweb.service.impl;





import com.alibaba.fastjson.JSON;

import com.yueke.common.core.domain.shop.YuekeShopClassify;
import com.yueke.common.core.domain.shop.YuekeShopGoods;
import com.yueke.common.core.exception.WoniuException;
import com.yueke.yuekeshop.shopmodel.dto.goods.ShopGoodsDto;
import com.yueke.yuekeshop.shopmodel.params.goods.GoodsIdOrNumParams;
import com.yueke.yuekeshop.shopmodel.params.goods.GoodsListParams;
import com.yueke.yuekeshop.shopmodel.params.goods.ShopGoodsParams;
import com.yueke.yuekeshop.shopweb.mapper.ShopClassifyMapper;
import com.yueke.yuekeshop.shopweb.mapper.ShopGoodsMapper;
import com.yueke.yuekeshop.shopweb.service.ShopGoodsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.cglib.beans.BeanMap;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.time.YearMonth;
import java.util.*;
import java.util.stream.Collectors;

@Service("shopGoodsService")
@Slf4j
public class ShopGoodsServicImpl implements ShopGoodsService {

    @Autowired
    private ShopGoodsMapper shopGoodsMapper;

    @Autowired
    private ShopClassifyMapper shopClassifyMapper;

    /**
     *  redis template
     */
    @Autowired
    private StringRedisTemplate stringRedisTemplate;



    /**
     *  测试redis
     * @param key
     * @return
     */
    @Override
    public String createRedisKey(String key) {
        String value = stringRedisTemplate.opsForValue().get(key);
        return value;
    }

    /**
     * 根据参数分类名称,新增一条分类记录
     * @param classifyName
     */
    @Override
    public void addClassify(String classifyName) {
        YuekeShopClassify shopClassify = new YuekeShopClassify();
        shopClassify.setClassifyName(classifyName);
        int insert = shopClassifyMapper.insert(shopClassify);
    }

    /**
     * 添加商品入库 shop:goods:id:
     * redis 商品库  campsite:1:goods:ids
     * @param shopGoodsParams
     */
    @Override
    public void addGoody(ShopGoodsParams shopGoodsParams) {
        YuekeShopGoods yuekeShopGoods = new YuekeShopGoods();
        yuekeShopGoods.setGoodsNumber(this.getShopNumber(shopGoodsParams.getCampsiteId()));
        yuekeShopGoods.setGoodsSales(0);
        yuekeShopGoods.setGoodsStatus("待上架");
        String goodsPicture = String.join(",", shopGoodsParams.getGoodsPictures());
        yuekeShopGoods.setGoodsPicture(goodsPicture);
        BeanUtils.copyProperties(shopGoodsParams,yuekeShopGoods);
        int insert = shopGoodsMapper.insert(yuekeShopGoods);
        HashMap<String, String> map = this.getNamValMap(yuekeShopGoods);
        stringRedisTemplate.opsForHash().putAll("shop:goods:id:"+yuekeShopGoods.getGoodsId(),map);
        stringRedisTemplate.opsForZSet().add("campsite:" + yuekeShopGoods.getCampsiteId() + ":goods:ids",yuekeShopGoods.getGoodsId()+"",System.currentTimeMillis());
    }

    /**
     *  把对象转化成map
     * @param obj
     * @return
     */
    public  HashMap<String, String> getNamValMap(Object obj) {
        HashMap<String, String> map = new HashMap<>();
        Field[] fieldArr = obj.getClass().getDeclaredFields();
        try {
            for (Field field : fieldArr) {
                field.setAccessible(true);
                if (field.get(obj) != null && !"".equals(field.get(obj).toString())) {
                    map.put(field.getName(), field.get(obj).toString());
                }
            }
        } catch (IllegalAccessException e) {
            log.error(e.getMessage());
        }
        return map;
    }
    /**
     * 抽取出商品编号  C:营地ID ++ T:时间戳
     * @param campsiteId
     * @return
     */
    public   String getShopNumber(Integer campsiteId) {
        return "C"+campsiteId+"T"+System.currentTimeMillis();
    }

    /**
     * 商品上架(可批量) campsite:1:goods:on:ids
     * @param goodsIdOrNumParamsList
     */
    @Override
    public void onGoodsSheIfList(List<GoodsIdOrNumParams> goodsIdOrNumParamsList) {
        goodsIdOrNumParamsList.forEach(GoodsIdOrNumParams ->{
            String campsiteId= this.getCampsiteId(GoodsIdOrNumParams.getGoodsNumber());

            Boolean isResult = stringRedisTemplate.opsForZSet().add("campsite:"+ campsiteId+ ":goods:on:ids",GoodsIdOrNumParams.getGoodsId()+"",System.currentTimeMillis());
            if (!isResult){
                throw new WoniuException(9301,"上架商品失败");
            }
        });

    }

    /**
     * 抽取营地id
     * @param goodsNumber
     * @return
     */
    private String getCampsiteId(String goodsNumber){
        return goodsNumber.substring(goodsNumber.indexOf("C")+1,goodsNumber.lastIndexOf("T"));
    }

    /**
     * 商品下架(可批量) campsite:1:goods:on:ids
     * @param goodsIdOrNumParamsList
     */
    @Override
    public void downGoodsSheIfList(List<GoodsIdOrNumParams> goodsIdOrNumParamsList) {
        goodsIdOrNumParamsList.forEach(goodsIdOrNumParams ->{
             String campsiteId= this.getCampsiteId(goodsIdOrNumParams.getGoodsNumber());
             stringRedisTemplate.opsForZSet().remove("campsite:"+campsiteId + ":goods:on:ids",goodsIdOrNumParams.getGoodsId()+"");
        });
    }

    /**
     * 未上架商品删除(可批量)
     * @param goodsIdOrNumParamsList
     */
    @Override
    public void deleteGoodsIds(List<GoodsIdOrNumParams> goodsIdOrNumParamsList) {
        goodsIdOrNumParamsList.forEach(goodsIdOrNumParams -> {
            String campsiteId= this.getCampsiteId(goodsIdOrNumParams.getGoodsNumber());
            Set<String> goodsOnIds = stringRedisTemplate.opsForZSet().range("campsite:" + campsiteId + ":goods:on:ids", 0, -1);
            boolean isContains = goodsOnIds.contains(goodsIdOrNumParams.getGoodsId());
            if (isContains){
                throw new WoniuException(500,"商品已上架不可删除{goodsNumber}:"+goodsIdOrNumParams.getGoodsNumber());
            }
            int i = shopGoodsMapper.deleteById(goodsIdOrNumParams.getGoodsId());
            stringRedisTemplate.opsForZSet().remove("campsite:" +campsiteId+ ":goods:ids",goodsIdOrNumParams.getGoodsId()+"");
        });
    }

    /**
     * 查询商品(可模糊)
     * @param goodsListParams
     * @return
     */
    @Override
    public List<ShopGoodsDto> selectOnGoodsList(GoodsListParams goodsListParams) {
           List<String> goodsIds = new ArrayList<>();
           List<ShopGoodsDto> shopGoodsDtoList = new ArrayList<>();
           List<ShopGoodsDto> shopGoodsDtos = this.getShopGoodsDtos(goodsListParams, goodsIds, shopGoodsDtoList);
          /* PageHelper.startPage(goodsListParams.getPageNum(),goodsListParams.getPageSize());
           PageInfo<ShopGoodsDto> shopPageGoodDto = new PageInfo<>(shopGoodsDtos);*/
        List<ShopGoodsDto> pageGoodsDto = shopGoodsDtos.stream()
                .skip(goodsListParams.getPageSize()*(goodsListParams.getPageNum() - 1))
                .limit(goodsListParams.getPageSize()).collect(Collectors.toList());
        if (goodsListParams.getGoodsStatus().equals("已上架")){
            shopGoodsDtos.stream().forEach(shopGoodsDto -> {
                shopGoodsDto.setGoodsStatus(goodsListParams.getGoodsStatus());
            });
        }
        return pageGoodsDto;

    }

    /**
     * 封装未上架商品(模糊查询)
     * @param goodsListParams
     * @param goodsIds
     * @param shopGoodsDtoList
     * @return
     */
    private List<ShopGoodsDto> getShopGoodsDtos(GoodsListParams goodsListParams, List<String> goodsIds, List<ShopGoodsDto> shopGoodsDtoList) {
        /**
         * 营地判断 取出相应营地集合
         */
        if (goodsListParams.getCampsiteId()==null){
            Set<String> campsiteList = stringRedisTemplate.opsForZSet().range("campsite:ids", 0, -1);
            if (goodsListParams.getGoodsStatus().equals("已上架")){
                List<String> goodsOnIds = this.getGoodsOnIds(campsiteList);
                goodsIds.addAll(goodsOnIds);
            }else{
                List<String> goodsDownIds = this.getGoodsDownIds(campsiteList);
                goodsIds.addAll(goodsDownIds);
            }
        }else {
            Set<String> campsiteList = new HashSet<>();
            campsiteList.add(goodsListParams.getCampsiteId()+"");
            if (goodsListParams.getGoodsStatus().equals("已上架")){
                List<String> goodsOnIds = this.getGoodsOnIds(campsiteList);
                goodsIds.addAll(goodsOnIds);

            }else{
                List<String> goodsDownIds = this.getGoodsDownIds(campsiteList);
                goodsIds.addAll(goodsDownIds);

            }
        }
        /**
         * 分类判断
         */
        if (goodsListParams.getClassifyId()==null){
            goodsIds.forEach(goodsId ->{
               YuekeShopGoods yueShopGoods = this.getYueShopGoods(goodsId,goodsListParams.getGoodsName());
               if (yueShopGoods==null){
                   return;
               }
                ShopGoodsDto shopGoodsDto = new ShopGoodsDto();
                BeanUtils.copyProperties(yueShopGoods,shopGoodsDto);
                shopGoodsDtoList.add(shopGoodsDto);
            });
        }else{
            goodsIds.forEach(goodsId ->{
                Integer classifyId = Integer.parseInt(this.getClassifyIdValue(goodsId, goodsListParams.getClassifyId()));
                System.out.println(goodsIds);
                if (goodsListParams.getClassifyId().equals(classifyId)){
                    YuekeShopGoods yueShopGoods = this.getYueShopGoods(goodsId,goodsListParams.getGoodsName());
                    if (yueShopGoods==null){
                        return;
                    }
                    ShopGoodsDto shopGoodsDto = new ShopGoodsDto();
                    BeanUtils.copyProperties(yueShopGoods,shopGoodsDto);
                    shopGoodsDtoList.add(shopGoodsDto);
                }
            });
            if (shopGoodsDtoList==null){
                return null;
            }
        }
        return shopGoodsDtoList;
    }

    /**
     * 封装商品名名称模糊查询
     * @param goodsId
     * @param goodsName
     * @return
     */
    private YuekeShopGoods getYueShopGoods(String goodsId,String goodsName) {
        if (goodsName!=null){
            String goodsNameValue = this.getGoodsNameValue(goodsId,goodsName);
            boolean isContains =goodsNameValue.contains(goodsName);
            if (isContains){
                Map<Object, Object> ShopGoodsMap = stringRedisTemplate.opsForHash().entries("shop:goods:id:"+goodsId);
                YuekeShopGoods yuekeShopGoods = JSON.parseObject(JSON.toJSONString(ShopGoodsMap),YuekeShopGoods.class);
                return yuekeShopGoods;
            }else {
                return null;
            }
        }else {
            Map<Object, Object> ShopGoodsMap = stringRedisTemplate.opsForHash().entries("shop:goods:id:"+goodsId);
            YuekeShopGoods yuekeShopGoods = JSON.parseObject(JSON.toJSONString(ShopGoodsMap),YuekeShopGoods.class);
            return yuekeShopGoods;
        }
    }

    /**
     * 取出商品分类属性
     * @param goodsId
     * @param key
     * @return
     */
    private String getClassifyIdValue(String goodsId,Object key) {
        String value = String.valueOf(stringRedisTemplate.opsForHash().get("shop:goods:id:" + goodsId, "classifyId"));
        Object o = stringRedisTemplate.opsForHash().get("shop:goods:id:" + goodsId, "classifyId");
        return value;
    }

    /**
     * 取出商品名称
     * @param goodsId
     * @param key
     * @return
     */
    private String getGoodsNameValue(String goodsId, Object key) {
        String value = String.valueOf(stringRedisTemplate.opsForHash().get("shop:goods:id:" + goodsId, "goodsName"));
        Object o = stringRedisTemplate.opsForHash().get("shop:goods:id:" + goodsId, "goodsName");
        return value;
    }

    /**
     * 抽取需要营地上架商品ids集合
     * @param campsiteList
     * @return
     */
    private List<String> getGoodsOnIds(Set<String> campsiteList) {
       List<String>  goodsOnIds = new ArrayList<>();
        campsiteList.forEach(campsiteId ->{
            Set<String> goodsIds = stringRedisTemplate.opsForZSet().range("campsite:" + campsiteId+ ":goods:on:ids", 0, -1);
            goodsOnIds.addAll(goodsIds);
            Collections.reverse(goodsOnIds); /* 控制输出顺序的地方 */
        });
        return goodsOnIds;
    }

    /**
     * 抽取需要营地未上架商品ids集合
     * @param campsiteList
     * @return
     */
    private List<String>  getGoodsDownIds(Set<String> campsiteList) {
        List<String>  goodsOnIds = new ArrayList<>();
        campsiteList.forEach(campsiteId ->{
            Set<String> goodsIds = stringRedisTemplate.opsForZSet().range("campsite:" + campsiteId+ ":goods:ids", 0, -1);
            goodsIds.removeAll(this.getGoodsOnIds(campsiteList));
            goodsOnIds.addAll(goodsIds);  /* 控制输出顺序的地方 */
            Collections.reverse(goodsOnIds);
        });
        return goodsOnIds;
    }


    /**
     * 查询商品详情
     * @param goodsId
     * @return
     */
    @Override
    public ShopGoodsDto selectGoodsById(Integer goodsId) {
        YuekeShopGoods yuekeShopGoods = shopGoodsMapper.selectById(goodsId);
        log.info("数据库返回结果{shopGoods}:"+yuekeShopGoods);
        ShopGoodsDto shopGoodsDto = new ShopGoodsDto();
        BeanUtils.copyProperties(yuekeShopGoods,shopGoodsDto);
        Set<String> campsiteList = stringRedisTemplate.opsForZSet().range("campsite:ids", 0, -1);
        List<String> goodsOnIds = this.getGoodsOnIds(campsiteList);
        boolean contains = goodsOnIds.contains(goodsId);
        if (contains){
            shopGoodsDto.setGoodsStatus("已上架");
        }
        return shopGoodsDto;
    }



    /**
     * 修改商品详情
     * @param shopGoodsParams
     * @return
     */
    @Override
    public void updateGoodsOne(ShopGoodsParams shopGoodsParams) {
        if (shopGoodsParams.getGoodsId()!=null){
            YuekeShopGoods yuekeShopGoods = new YuekeShopGoods();
            String goodsPicture = String.join(",", shopGoodsParams.getGoodsPictures());
            yuekeShopGoods.setGoodsPicture(goodsPicture);
            BeanUtils.copyProperties(shopGoodsParams,yuekeShopGoods);
            HashMap<String, String> map = this.getNamValMap(yuekeShopGoods);
            stringRedisTemplate.opsForHash().delete("shop:goods:id:"+yuekeShopGoods.getGoodsId());
            stringRedisTemplate.opsForHash().putAll("shop:goods:id:"+yuekeShopGoods.getGoodsId(),map);
            stringRedisTemplate.opsForZSet().add("campsite:" + yuekeShopGoods.getCampsiteId() + ":goods:ids",yuekeShopGoods.getGoodsId()+"",System.currentTimeMillis());
        }else {
            throw new WoniuException(500,"商品ID为null");
        }
    }
}
